﻿using System;
using System.Collections.Generic;
using System.Threading;
using WebSocket4Net;
using WS.EKA.Utility;

namespace WS.EKA.UI.Business
{
    public class WebSocketClient
    {

        static Dictionary<WebSocketClientType, WebSocket> clients = new Dictionary<WebSocketClientType, WebSocket>();
        /// <summary>
        /// 我们需要在系统websocket server成功启动后，创建并保存客户端连接
        /// </summary>
        static WebSocketClient()
        {
            RegisteWebSocketClient();
        }

        //在系统成功启动web socket server后执行
        public static void Initialize()
        {
        }

        public static void SendMessage(WebSocketClientType clientType, string message)
        {
            if (!clients.ContainsKey(clientType))
                throw new Exception(clientType + "对应的会话不存在");
            try
            {
                if (WebSocketState.Connecting == clients[clientType].State)
                {
                    int interval = 0;
                    while (interval < 2000)
                    {
                        Thread.Sleep(50);
                        interval += 50;
                    }
                }
                if (WebSocketState.Open != clients[clientType].State)
                {
                    RegisteWebSocketClient(clientType);
                }
                clients[clientType].Send(message);
            }
            catch (Exception ex)
            {
                Logger.Error(clientType.ToString() + "发生异常", ex, "websocketclient SendMessage");
            }
        }

        public static void StartClient(string url, WebSocketClientType clientType, WebSocketVersion version, string subProtocol)
        {
            string protocol = string.IsNullOrEmpty(subProtocol) ? "basic" : subProtocol;
            var client = CreateClient(url, version, true, protocol);
            clients[clientType] = client;
        }

        public static void CloseAll()
        {
            foreach (var client in clients)
            {
                Close(client.Key);
            }
            clients.Clear();
        }

        public static void Close(WebSocketClientType clientType)
        {
            var client = clients[clientType];
            if (client == null)
                throw new Exception(clientType + "对应的会话未创建");
            if (client.State == WebSocketState.Open || client.State == WebSocketState.None)
                client.Close();
            clients.Remove(clientType);
        }

        private static WebSocket CreateClient(string url, WebSocketVersion version, bool autoConnect, string subProtocol = "basic")
        {
            //ws://127.0.0.1:9999/path
            var webSocketClient = new WebSocket(url, subProtocol, version);
            webSocketClient.Opened += new EventHandler(webSocketClient_Opened);
            webSocketClient.Closed += new EventHandler(webSocketClient_Closed);
            webSocketClient.DataReceived += new EventHandler<WebSocket4Net.DataReceivedEventArgs>(webSocketClient_DataReceived);
            webSocketClient.MessageReceived += new EventHandler<MessageReceivedEventArgs>(webSocketClient_MessageReceived);

            if (autoConnect)
            {
                webSocketClient.Open();
                //client建立连接需要几秒时间
                int seconds = 0;
                while (webSocketClient.State != WebSocketState.Open)
                {
                    Thread.Sleep(100);
                    seconds += 1;
                    if (seconds > 60)
                    {
                        throw new Exception("地址为" + url + "的websocket客户端连接超过6秒，请检查网络及服务");
                    }
                }
            }
            return webSocketClient;
        }

        #region events
        private static void webSocketClient_MessageReceived(object sender, MessageReceivedEventArgs message)
        {
            //能正确触发
            //Console.WriteLine(message.Message);
        }
        private static void webSocketClient_DataReceived(object sender, WebSocket4Net.DataReceivedEventArgs e)
        {
            //经测试不能触发
        }
        private static void webSocketClient_Opened(object sender, EventArgs e)
        {
            //能正确触发
        }

        private static void webSocketClient_Closed(object sender, EventArgs en)
        {
            //经测试不能触发,但客户端能成功与服务端断开连接
            //源程序需要在State == WebSocketState.None才触发这个事件
        }
        #endregion

        private static void RegisteWebSocketClient()
        {
            RegisteWebSocketClient(WebSocketClientType.None);
        }

        private static void RegisteWebSocketClient(WebSocketClientType type)
        {
            var clients = new WebSocketXmlAnalysis().Deserialize();
            foreach (var client in clients.Client)
            {
                if (type == WebSocketClientType.None)
                    WebSocketClient.StartClient(client.URL, client.WebSocketClientType, client.WebSocketVersion, client.SubProtocol);
                else
                {
                    if (type == client.WebSocketClientType)
                    {
                        WebSocketClient.StartClient(client.URL, client.WebSocketClientType, client.WebSocketVersion, client.SubProtocol);
                        break;
                    }
                }
            }
        }
    }
}
